using System.Net;
using System.Security.Claims;
using JWTAPI.AuthorInfo;
using JWTAPI.AuthorInfo.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Senparc.CO2NET.WebApi;
using Senparc.CO2NET.WebApi.WebApiEngines;

var builder = WebApplication.CreateBuilder(args);


// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

//跨域
builder.Services.AddCors();

builder.Services.AddIdentityServer()
    .AddDeveloperSigningCredential(persistKey: false)//添加开发人员签名凭据(扩展在每次启动时，为令牌签名创建了一个临时密钥。在生成环境需要一个持久化的密钥 builder.AddSigningCredential)
    .AddInMemoryIdentityResources(Ids4Config.GetIdentityResources())//Api 资源
    .AddInMemoryApiResources(Ids4Config.GetApis())//Api的客户端
    .AddInMemoryClients(Ids4Config.GetClients())
    //.AddTestUsers(Ids4Config.Users)
    .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()//自定义用户验证。
    .AddProfileService<ResourceOwnerPasswordProfileService>();


        // 添加认证
 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//添加授权模式 services.AddAuthentication("Bearer")
                    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
                    {
                        options.Authority = "https://localhost:5000";//授权服务器地址(/identityserver4 地址 也就是本项目地址) 实际工作中写在appsettings.json文件中。
                        options.RequireHttpsMetadata = true ;//是否是https
                        //options.Audience = "ids4.api offline_access openid profile";
                        options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                        {
                            ValidateAudience = false,
                        };
                        options.Events = new JwtBearerEvents
                        {
                            // 身份认证失败
                            OnAuthenticationFailed = async context =>
                            {
                                var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents));
                                logger.LogError("Authentication failed.", context.Exception.Message);
                                var responseResult = new ResponseResult<TokenRespnseResult>()
                                {
                                    Code = (int)HttpStatusCode.Unauthorized,
                                    Message = "对不起！接口身份授权失败，您无权访问！"
                                };
                                context.Response.ContentType = "application/json";
                                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                                await context.Response.WriteAsync(JsonConvert.SerializeObject(responseResult, Formatting.Indented));
                            },
                            // token口令验证成功
                            //oidc 解决User.Identity.Name 为空解决方法
                            OnTokenValidated = context =>
                            {
                                var identity = context.Principal.Identity as ClaimsIdentity;
                                if (identity != null)
                                {
                                    // Add the Name ClaimType. This is required if we want User.Identity.Name to actually return something!
                                    if (!context.Principal.HasClaim(c => c.Type == ClaimTypes.Name) &&
                                    identity.HasClaim(c => c.Type == "name"))
                                        identity.AddClaim(new Claim(ClaimTypes.Name, identity.FindFirst("name").Value));

                                    // Check if token names are stored in Properties
                                    if (context.Properties.Items.ContainsKey(".TokenNames"))
                                    {
                                        // Token names a semicolon separated
                                        string[] tokenNames = context.Properties.Items[".TokenNames"].Split(';');

                                        // Add each token value as Claim
                                        foreach (var tokenName in tokenNames)
                                        {
                                            // Tokens are stored in a Dictionary with the Key ".Token.<token name>"
                                            string tokenValue = context.Properties.Items[$".Token.{tokenName}"];
                                            identity.AddClaim(new Claim(tokenName, tokenValue));
                                        }
                                    }
                                }
                                return Task.CompletedTask;
                            }
                        };
                    });

//添加动态Api 代码
var bm = builder.Services.AddMvcCore().AddApiExplorer().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);


var docXmlPath = (Func<IWebHostEnvironment, string>) (env => Path.Combine(env.ContentRootPath, "App_Data", "JWTAPI.xml"));



builder.Services.AddAndInitDynamicApi(bm, options =>
{
    //  options.DocXmlPath = docXmlPath;
    options.DefaultRequestMethod = ApiRequestMethod.Get;
    options.BaseApiControllerType = null;
    options.CopyCustomAttributes = true;
    options.TaskCount = Environment.ProcessorCount * 4;
    options.ShowDetailApiLog = true;
    options.AdditionalAttributeFunc = null;
    options.ForbiddenExternalAccess = false;
});

   
var app = builder.Build();

app.UseDeveloperExceptionPage();

app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());


app.UseRouting();

app.UseIdentityServer();

app.UseSwagger();

app.UseSwaggerUI();


app.UseHttpsRedirection();

///使用认证中间件
app.UseAuthentication();

///使用授权中间件
app.UseAuthorization();


app.UseEndpoints(endpoint =>
{

    endpoint.MapControllers();

});



app.Run();